from moviepy import ImageClip
from typing import Tuple
from config import config


def create_animated_image_clip(
    image_path: str,
    duration: float,
    video_size: Tuple[int, int] = None,
    animation_type: str = "ken_burns",
) -> ImageClip:
    if video_size is None:
        video_size = config.video.size
    image = ImageClip(image_path, duration=duration)
    image = image.resized(height=video_size[1]).with_position("center")
    
    animation_map = {
        "ken_burns": lambda: create_ken_burns_effect(image, video_size),
        "zoom_in": lambda: create_zoom_in_effect(image, video_size),
        "zoom_out": lambda: create_zoom_out_effect(image, video_size),
        "slide_left": lambda: create_slide_left_effect(image, video_size),
        "slide_right": lambda: create_slide_right_effect(image, video_size),
        "fade": lambda: image,
    }
    
    return animation_map.get(animation_type, lambda: image)()


def create_ken_burns_effect(image: ImageClip, video_size: Tuple[int, int]) -> ImageClip:
    oversized_image = image.resized(height=video_size[1] * 1.2)
    
    def scale_func(t):
        progress = t / image.duration
        return 1.0 + 0.1 * progress
    
    def position_func(t):
        progress = t / image.duration
        x_offset = -15 + 30 * progress
        y_offset = -10 + 20 * progress
        return (video_size[0]//2 + x_offset, video_size[1]//2 + y_offset)
    
    return oversized_image.resized(scale_func).with_position(position_func)


def create_zoom_in_effect(image: ImageClip, video_size: Tuple[int, int]) -> ImageClip:
    def scale_func(t):
        progress = t / image.duration
        return 1.0 + 0.3 * progress
    
    return image.resized(scale_func).with_position("center")


def create_zoom_out_effect(image: ImageClip, video_size: Tuple[int, int]) -> ImageClip:
    def scale_func(t):
        progress = t / image.duration
        return 1.3 - 0.3 * progress
    
    oversized_image = image.resized(height=video_size[1] * 1.3)
    return oversized_image.resized(scale_func).with_position("center")


def create_slide_left_effect(image: ImageClip, video_size: Tuple[int, int]) -> ImageClip:
    oversized_image = image.resized(height=video_size[1] * 1.1)
    
    def position_func(t):
        progress = t / image.duration
        x_offset = 50 - 100 * progress
        return (video_size[0]//2 + x_offset, video_size[1]//2)
    
    return oversized_image.with_position(position_func)


def create_slide_right_effect(image: ImageClip, video_size: Tuple[int, int]) -> ImageClip:
    oversized_image = image.resized(height=video_size[1] * 1.1)
    
    def position_func(t):
        progress = t / image.duration
        x_offset = -50 + 100 * progress
        return (video_size[0]//2 + x_offset, video_size[1]//2)
    
    return oversized_image.with_position(position_func)